﻿#region Librerias

using System;
using System.Collections.Generic;
using System.Text;
using ESF.General.Text;
using ESF.General;
using System.IO;
using System.Transactions;
using System.Diagnostics;
using System.Data;
using System.Windows.Forms;

#endregion


namespace ESF.Data.DBFileExecutor
{
	public static class Program
	{
		#region Constantes
		
		private const string DBFILESEXECUTORORDER_FILENAME = "dbFilesExecutorOrder.txt";
		
		private const string MAINDB_CONFIGNAME = "MAINDB";
		
		private const string BREAK_LINE = "BREAK";

		private const string COMMENT_STARTLINE = "#";
		
		#endregion
	
	
		#region Punto de Inicio
	
		public static void Main (string[] pArgs)
		{
			ArgsReader argsReader;
			
			Stopwatch stopWatchAll;
			
			
			stopWatchAll = new Stopwatch ();
			stopWatchAll.Start ();
			
			try
			{
				argsReader = new ArgsReader (pArgs);
				
				ExecuteDBFiles 
				(
					string.Format("{0}{1}{2}",
						argsReader.GetArg(false, "f", Application.StartupPath), 
						Path.DirectorySeparatorChar, 
						DBFILESEXECUTORORDER_FILENAME),
					argsReader.GetArg(true, "cn", MAINDB_CONFIGNAME),
                    argsReader.GetArgBool (false, "t", true).Value
				);

				stopWatchAll.Stop();

				Console.WriteLine("*** All files where succesfully commited in {0} ***", TextHelper.ToStringMS (stopWatchAll.ElapsedMilliseconds));
			}
			catch (Exception pEx)
			{
				Log.Error (pEx);
				
				stopWatchAll.Stop();

				Console.WriteLine("*** Error happens in {0} ***", TextHelper.ToStringMS (stopWatchAll.ElapsedMilliseconds));

				ShowUse ();
			}
		}
		
		#endregion
		
		
		#region Funciones
		
		private static void ExecuteDBFiles (string pRelativeFilesToExecListFilename, string pConfigName, bool pUseTransaction)
		{
			string mainFolder;
			
			
			DbWriter dbWriter;
			
			string [] fileList;
			
		
			pRelativeFilesToExecListFilename = Path.GetFullPath (pRelativeFilesToExecListFilename);

			if (!File.Exists (pRelativeFilesToExecListFilename))
			{
				throw new GenericInfoException (string.Format ("The file {0} with list of files does not exist", pRelativeFilesToExecListFilename));
			}
			
			mainFolder = Path.GetDirectoryName (pRelativeFilesToExecListFilename);
			
			Console.WriteLine ("Initializing connection manager for {0}", pConfigName);
			

			dbWriter = new DbWriter (pConfigName);
			
			fileList = File.ReadAllLines (pRelativeFilesToExecListFilename);
				
			Console.WriteLine ("Registered {0} lines...", fileList.Length);
		
			if (fileList.Length == 0) 
			{
				Console.Error.WriteLine ("No files were found!"); 
				return; 
			}


			Console.WriteLine ("Ready to start {0} transaction? Y for YES, anyelse NO?", pUseTransaction ? "with" : "without");

			if (Console.ReadLine () != "Y")
			{
				Console.WriteLine ("Cancelled!!!");
				return;
			}

            if (pUseTransaction)
            {
                using (ContextSingleTransactionScope TS = dbWriter.CreateContextSingleTransactionScope())
                {
                    ExecuteFileList(dbWriter, mainFolder, fileList);

                    Console.Write("Confirm the transaction (Y)? ");

                    if (Console.ReadKey().KeyChar == 'Y')
                    {
                        TS.Complete();
                    }
                }
            }
            else
            {
                ExecuteFileList(dbWriter, mainFolder, fileList);

                Console.Write("Transaction completed!!!");
            }
		}


		private static void ExecuteFileList (DbWriter pWriter, string pMainFolder, string [] pFileList)
		{
			int index;
			int reallyExecutedCount;
			
			string currentFilename;


			index = 0;
			reallyExecutedCount = 0;
			
			
			foreach (string relativeFileName in pFileList)
			{
				index++;
				
				if (string.IsNullOrEmpty (relativeFileName) || relativeFileName.StartsWith (COMMENT_STARTLINE)) 
				{
					continue; 
				}
					
				if (relativeFileName == BREAK_LINE)
				{
					break;
				}
				
				currentFilename = string.Format ("{0}{1}{2}", pMainFolder, Path.DirectorySeparatorChar, relativeFileName);
				
				if (!File.Exists (currentFilename))
				{
					throw new Exception (string.Format ("The file {0} is not in the folder {1}", currentFilename, pMainFolder));
				}
					
				Console.WriteLine ("Reading and Executing file {0}/{1}: {2}... ", index, pFileList.Length, relativeFileName);

				
						
				foreach (string cmdSQL in TextHelper.SplitLines (File.ReadAllText (currentFilename), "GO"))
				{
					pWriter.Execute (pWriter.CreateCommandWithoutTimeout (cmdSQL));
				}

				reallyExecutedCount ++;
			}
		}
		
		
		private static void ShowUse ()
		{
			Console.WriteLine (new String ('-', 76));

			Console.WriteLine ("ESF.Data.DBFileExecutor: SQL File Executor Batch for DB");
			Console.WriteLine ();
			Console.WriteLine ("This program reads a file with a sorted list of relative locations");
			Console.WriteLine ("of files (*.sql) with SQL comands for a database.");
			Console.WriteLine ("The database used is [-cn (connection string name from settings] [-t (use transaction) ]");
			Console.WriteLine(); 
			Console.WriteLine("Use (remember must be a folder with a file {0}):", DBFILESEXECUTORORDER_FILENAME);
			Console.WriteLine("ESF.Data.DBFileExecutor.exe -f (folderName) [-cn connectionName] [-t true|false]");
			Console.WriteLine(); 
			Console.WriteLine("Example of Use:");
			Console.WriteLine("ESF.Data.DBFileExecutor.exe -f c:\\sqls -cn DB");

			Console.WriteLine(new String('-', 76));
		}
		
		#endregion
	}
}
